準備往 ES 塞大量資料前,有件事怪怪的,我好像沒有給資料欄位 ( Data Field ) 指定資料型別 ( Data Type ),對比關聯式資料庫,也就是 Schema。在 Elasticsearch 中,是透過 Mapping 來進行。今天就來玩玩 Mapping 吧!
在 Elasticsearch 中,Mapping 分成兩類:
Explicit mapping:
由使用者自行定義的的資料型別
Dynamic mapping:
ES 自動產生
前幾天新建立的 Index,很顯然會是 Dynamic mapping,我 Index 的盤後資訊 Document 如下:
{
"stock_id":"0050",
"date":"2020-09-11",
"volume":2905291,
"open":103.20,
"high":103.35,
"low":102.80,
"close":103.25
}
讓我們來瞧瞧 ES 如何幫我定義 Data Type。透過以下的 API:
GET /history-prices/_mapping
得到以下的 mapping :
{
"history-prices" : {
"mappings" : {
"properties" : {
"close" : {
"type" : "float"
},
"date" : {
"type" : "date"
},
"high" : {
"type" : "float"
},
"low" : {
"type" : "float"
},
"open" : {
"type" : "float"
},
"stock_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"volume" : {
"type" : "long"
}
}
}
}
}
看起來不錯,除了 stock_id 和 volume。
現在我們來分析一下 stock_id (股票代號) 和 volume (成交股數) 這兩個欄位的 Data Type 應該如何設計。
ES 為 stock_id 設定的 data type 為 "text",在查詢的時候會以全文檢索的方式進行,只要文字符合,就會被查出來,這顯然需要小擔心一下;此外, ES 還為 stock_id 設定了multi-fields,根據官方文件, 可以用來做 sorting 和 aggregations,這個需求對搜尋股票代號來說,也挺多餘的。
股票代號有獨一無二的特性,所以最適合的 Data Type ,我認為應該是 " keyword ",它的特性是在搜尋時會 "exact matching"。keyword field 是由 keyword anayler 分析,keyword anayler 其實就是一種 no-op (不做任何事) 的 analyer。有關 analyer ,我找一天再來深入研究。
ES 設定的 data type 的 long。來看看 long 和 integer 的數值範圍:
其中 integer 的最大正整數為 2,147,483,647,換算成張數大約為 200萬張。如果是日成交量,單日成效量能超過百萬張已屬難見,到 2 百萬張應該是此生難見,所以我認為用 integer type 足矣。這樣能有效的節省儲存空間。
但如果要做週/月的統計,超過 integer 範圍就比較容易達成,我的設計會把週/月的統計,放在另一個 Index,並且 volume 欄位設計成 long。
透過下面的 API 可以在建立新的 Index 的同時,建立 Mapping。
PUT /history-prices-daily
{
"mappings": {
"properties": {
"close" : {
"type" : "float"
},
"date" : {
"type" : "date"
},
"high" : {
"type" : "float"
},
"low" : {
"type" : "float"
},
"open" : {
"type" : "float"
},
"stock_id" : {
"type" : "keyword"
},
"volume" : {
"type" : "integer"
}
}
}
}
酷! 這下資料格式的問題搞定了。下一步,繼續研究如何上傳大量資料!